package ca.llsutherland.nfl.facade;

import ca.llsutherland.nfl.domain.Conference;
import ca.llsutherland.nfl.domain.Division;
import ca.llsutherland.nfl.domain.DomainObject;
import ca.llsutherland.nfl.domain.NamedDomainObject;
import ca.llsutherland.nfl.domain.Person;
import ca.llsutherland.nfl.domain.Role;
import ca.llsutherland.nfl.domain.Season;
import ca.llsutherland.nfl.domain.Team;
import ca.llsutherland.nfl.domain.User;
import ca.llsutherland.nfl.domain.WeekType;
import ca.llsutherland.nfl.exception.ValidationException;
import ca.llsutherland.nfl.util.Constants;
import ca.llsutherland.nfl.util.StringUtil;

public class BaseFacade {

	protected void assertValidDomainObject(DomainObject dobj, Class<DomainObject> aClass){
		assertNotNull(dobj, aClass);
		assertValidId(dobj, aClass);
	}
	
	protected void assertValidNamedDomainObject(NamedDomainObject ndobj){
		assertValidName(ndobj, NamedDomainObject.class);
	}
	
	private void assertValidName(NamedDomainObject ndobj, Class<NamedDomainObject> aClass) {
		String name = ndobj.getName();
		
		if(StringUtil.isBlankString(name)){
			String message = "Name field for " + aClass.getSimpleName() + " is empty or null.";
			throw new ValidationException(message);
		}
		
		if(!StringUtil.containsOnlyValidCharacters(name)){
			String message = "Name field for " + aClass.getSimpleName() + " is empty or null.";
			throw new ValidationException(message);
		}
	}

	protected void assertValidId(DomainObject dobj, Class<DomainObject> aClass) {
		Long id = dobj.getId();
		if(id == null){
			String message = "ID for Domain Object: " + aClass.getName() + " is null";
			throw new ValidationException(message);
		}
	}
	
	protected void assertNotNull(DomainObject dobj, Class<DomainObject> aClass) {
		if(dobj == null){
			String message = "Domain Object: " + aClass.getName() + " is null";
			throw new ValidationException(message);
		}
	}
	
	protected void assertValidNewUser(User newUser) {
		if(newUser == null){
			throw new ValidationException(Constants.PROGRAMMER_ERROR_USER_CAN_NOT_BE_NULL);
		}
		
		if(newUser.getPeople() == null || newUser.getPeople().size() == 0){
			throw new ValidationException(Constants.PROGRAMMER_ERROR_USER_MUST_HAVE_PERSON);
		}
		
		if(newUser.getRole() == null){
			throw new ValidationException(Constants.PROGRAMMER_ERROR_USER_MUST_HAVE_ROLE);
		}
		
		if(newUser.getUsername() == null){
			throw new ValidationException(Constants.USERNAME_CAN_NOT_BE_NULL_ERROR);
		}
		if(newUser.getUsername().trim().length() == 0){
			throw new ValidationException(Constants.USERNAME_CAN_NOT_BE_EMPTY_ERROR);
		}
		if(!StringUtil.containsOnlyValidCharacters(newUser.getUsername())){
			throw new ValidationException(Constants.USERNAME_CONTAINS_INVALID_CHARACTERS_ERROR);
		}
		if(newUser.getPassword() == null){
			throw new ValidationException(Constants.PASSWORD_CAN_NOT_BE_NULL_ERROR);
		}
		if(newUser.getPassword().trim().length() == 0){
			throw new ValidationException(Constants.PASSWORD_CAN_NOT_BE_EMPTY_ERROR);
		}
	}
	
	protected void assertValidNewPerson(Person newPerson) {
		if(newPerson == null){
			throw new ValidationException(Constants.PROGRAMMER_ERROR_PERSON_CAN_NOT_BE_NULL);
		}
		assertUserId(newPerson);

		assertFirstName(newPerson);
		assertLastName(newPerson);
		assertLocation(newPerson);
		assertEmail(newPerson);
		assertPhoneNumber(newPerson);
	}

	private void assertUserId(Person newPerson) {
		if(newPerson.getUserId() == null){
			throw new ValidationException(Constants.PROGRAMMER_ERROR_PERSON_HAS_NO_USER);
		}
	}

	private void assertPhoneNumber(Person newPerson) {
		if(newPerson.getPhoneNumber() == null){
			throw new ValidationException(Constants.PERSON_PHONE_NUMBER_CAN_NOT_BE_NULL_ERROR);
		}
		if(newPerson.getPhoneNumber().trim().length() == 0){
			throw new ValidationException(Constants.PERSON_PHONE_NUMBER_CAN_NOT_BE_EMPTY_ERROR);
		}
		if(!StringUtil.isOnlyNumeric(newPerson.getPhoneNumber())){
			throw new ValidationException(Constants.PERSON_PHONE_NUMBER_CONTAINS_INVALID_CHARACTERS_ERROR);
		}
		if(newPerson.getPhoneNumber().trim().length() != 10){
			throw new ValidationException(Constants.PERSON_PHONE_NUMBER_IS_TOO_SHORT_ERROR);
		}
	}

	private void assertEmail(Person newPerson) {
		if(newPerson.getEmail() == null){
			throw new ValidationException(Constants.PERSON_EMAIL_CAN_NOT_BE_NULL_ERROR);
		}
		if(newPerson.getEmail().trim().length() == 0){
			throw new ValidationException(Constants.PERSON_EMAIL_CAN_NOT_BE_NULL_ERROR);
		}
		if(!StringUtil.containsAtSymbol(newPerson.getEmail())){
			throw new ValidationException(Constants.PERSON_EMAIL_CONTAINS_INVALID_CHARACTERS_ERROR);
		}
	}

	private void assertLocation(Person newPerson) {
		if(newPerson.getLocation() == null){
			throw new ValidationException(Constants.PERSON_LOCATION_CAN_NOT_BE_NULL_ERROR);
		}
		if(newPerson.getLocation().trim().length() == 0){
			throw new ValidationException(Constants.PERSON_LOCATION_CAN_NOT_BE_NULL_ERROR);
		}
		if(!StringUtil.isOnlyAlphabetical(newPerson.getLocation())){
			throw new ValidationException(Constants.PERSON_LOCATION_CONTAINS_INVALID_CHARACTERS_ERROR);
		}
	}

	private void assertLastName(Person newPerson) {
		if(newPerson.getLastname() == null){
			throw new ValidationException(Constants.PERSON_LASTNAME_CAN_NOT_BE_NULL_ERROR);
		}
		if(newPerson.getLastname().trim().length() == 0){
			throw new ValidationException(Constants.PERSON_LASTNAME_CAN_NOT_BE_NULL_ERROR);
		}
		if(!StringUtil.isOnlyAlphabetical(newPerson.getLastname())){
			throw new ValidationException(Constants.PERSON_LASTNAME_CONTAINS_INVALID_CHARACTERS_ERROR);
		}
	}

	private void assertFirstName(Person newPerson) {
		if(newPerson.getFirstname() == null){
			throw new ValidationException(Constants.PERSON_FIRSTNAME_CAN_NOT_BE_NULL_ERROR);
		}
		if(newPerson.getFirstname().trim().length() == 0){
			throw new ValidationException(Constants.PERSON_FIRSTNAME_CAN_NOT_BE_NULL_ERROR);
		}
		if(!StringUtil.isOnlyAlphabetical(newPerson.getFirstname())){
			throw new ValidationException(Constants.PERSON_FIRSTNAME_CONTAINS_INVALID_CHARACTERS_ERROR);
		}
	}
	
	protected void assertValidNewConference(Conference conference) {
		assertValidNamedDomainObject(conference);
	}
	
	protected void assertValidNewDivision(Division division) {
		assertValidNewConference(division.getConference());
		assertValidNamedDomainObject(division);
	}
	
	protected void assertValidNewTeam(Team newTeam) {
		if(newTeam == null){
			throw new ValidationException(Constants.PROGRAMMER_ERROR_NULL_TEAM);
		}
		
		if(newTeam.getDivision() == null){
			throw new ValidationException(Constants.PROGRAMMER_ERROR_NULL_DIVISION_FOR_TEAM);
		}
		
		if(newTeam.getCity() == null){
			throw new ValidationException(Constants.PROGRAMMER_ERROR_TEAM_CITY_IS_NULL);
		}
		
		if(newTeam.getCity().length() == 0){
			throw new ValidationException(Constants.PROGRAMMER_ERROR_TEAM_CITY_IS_NULL);
		}
		if(newTeam.getNickname() == null){
			throw new ValidationException(Constants.PROGRAMMER_ERROR_TEAM_NICKNAME_IS_NULL);
		}
		
		if(newTeam.getNickname().length() == 0){
			throw new ValidationException(Constants.PROGRAMMER_ERROR_TEAM_NICKNAME_IS_NULL);
		}
		if(newTeam.getShortCity() == null){
			throw new ValidationException(Constants.PROGRAMMER_ERROR_TEAM_SHORT_CITY_IS_NULL);
		}
		
		if(newTeam.getShortCity().length() == 0){
			throw new ValidationException(Constants.PROGRAMMER_ERROR_TEAM_SHORT_CITY_IS_NULL);
		}
		if(newTeam.getShortNickname() == null){
			throw new ValidationException(Constants.PROGRAMMER_ERROR_TEAM_SHORT_NICKNAME_IS_NULL);
		}
		
		if(newTeam.getShortNickname().length() == 0){
			throw new ValidationException(Constants.PROGRAMMER_ERROR_TEAM_SHORT_NICKNAME_IS_NULL);
		}
	}
	
	protected void assertValidNewSeason(Season season) {
		assertValidNamedDomainObject(season);
		
		if(!StringUtil.isOnlyNumeric(season.getName())){
			throw new ValidationException(Constants.SEASON_NAME_CONTAINS_INVALID_CHARACTERS_ERROR);
		}
	}
	
	protected void assertValidNewWeekType(WeekType weekType) {
		assertValidNamedDomainObject(weekType);
		
		if(!StringUtil.isOnlyAlphabetical(weekType.getName())){
			throw new ValidationException(Constants.PROGRAMMER_ERROR_WEEK_TYPE_NAME_CONTAINS_INVALID_CHARACTERS);
		}
	}
	
	protected void assertValidNewRole(Role role) {
		assertValidNamedDomainObject(role);
		
		if(!StringUtil.isOnlyAlphabetical(role.getName())){
			throw new ValidationException(Constants.ROLE_NAME_CONTAINS_INVALID_CHARACTERS_ERROR);
		}
	}
}
